//
//  HKNetService.m
//  HKNetService
//
//  Created by 胡锦涛 on 2018/6/12.
//  Copyright © 2018年 胡锦涛. All rights reserved.
//

#import "HKNetService.h"
#import "AFNetworking.h"
#import "HKNetWorkConfig.h"
#import "HKCache.h"
#import <objc/runtime.h>
#import "HKIdentify.h"
#import "MyUUIDManager.h"
#import "HKMacro.h"
#import "HKNetService+Config.h"

#define MyUUID [MyUUIDManager getUUID]

NSString * const HKServiceRoot = @"HKServiceRoot";
NSString * const NET_BundleVersion = @"CFBundleVersion";
NSString * const CODE = @"code";
NSString * const MSG = @"message";

@interface HKNetService()
@property (nonatomic, strong) HKCache *cache;
@property (nonatomic, copy) HKCallBack success;
@property (nonatomic, copy) HKCallBack failure;

@property (nonatomic, strong) NSString * code ;//返回状态码
@property (nonatomic, strong) NSString * message ;//返回信息
@end

@implementation HKNetService

static HKNetService *_sharedInstance;
+(instancetype)sharedInstance{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[HKNetService alloc]init];
        [_sharedInstance configWithDic:nil];
        [[AFNetworkReachabilityManager sharedManager] startMonitoring];
    });
    [_sharedInstance cancel];
    return _sharedInstance;
}

static HKNetService *_jsonManager;
+(instancetype)jsonManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _jsonManager = [[HKNetService alloc]init];
        _jsonManager.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
        [_jsonManager configWithDic:nil];
    });
    [_jsonManager cancelJson];
    return _jsonManager;
}

- (void)configWithDic:(NSDictionary*)params {
    /*
     @{@"code":@"code",
       @"message":@"message"
     }
     */
    if ([params valueForKey:CODE] && [params valueForKey:MSG] && params != [NSNull class] && params != nil) {
        self.code = [params valueForKey:CODE];
        self.message = [params valueForKey:MSG];
    }else {
        self.code = CODE;
        self.message = MSG;
    }
}

-(void)cancelJson {
    _shouldCache = NO;
    if (_resultMessage) {
        [_resultMessage reset];
    } else {
        _resultMessage = [[HKResultMessage alloc] init];
    }
}

-(void)cancel{
    _sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
    _shouldCache = NO;
    if (_resultMessage) {
        [_resultMessage reset];
    } else {
        _resultMessage = [[HKResultMessage alloc] init];
    }
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _sessionManager = [[AFHTTPSessionManager manager]initWithBaseURL:nil];
        _sessionManager.requestSerializer.timeoutInterval = HKNetworkTimeoutSeconds;//设置超时时间
        _sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
        _sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        _sessionManager.operationQueue.maxConcurrentOperationCount = 10;//设置最大线程数
        //client端不用安装证书和不用验证域名
        _sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        [_sessionManager.securityPolicy setValidatesDomainName:NO];
    
        // 2.设置证书模式
        //NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"xbapi.miguxue.com" ofType:@"cer"];
        //NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
        //_sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:cerData, nil]];
        //_sessionManager.securityPolicy.allowInvalidCertificates = YES;
        //[_sessionManager.securityPolicy setValidatesDomainName:YES];
        
        //FIXME:使用配置项-处理
        [self configHandle];
    }
    return self;
}
#define FAILURE(errorCode) [self.resultMessage setErrorCode:errorCode];if(failure) failure(nil,self.resultMessage);
- (void)sendGETWithUrl:(NSString*)url params:(NSDictionary*)params success:(HKCallBack)success failure:(HKCallBack)failure {
    _success = [success copy];
    _failure = [failure copy];
    
    if (_shouldCache && [self hasCacheWithUrl:url Params:params]) {
        return;
    }
    
    if (self.isReachable) {
        [self addRequestHeaderWithIsFormData:NO];//默认非表单提交
        HKNetWeakSelf
        [_sessionManager GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            HKNetStrongSelf
            HKURLResponse *response = [[HKURLResponse alloc]initWithSessionDataTask:task
                                                                      requestParams:params
                                                                       responseData:responseObject
                                                                             status:HKResponseStatusSuccess];
#if HK_DEBUG
            NSLog(@"\n网络请求url:\n%@",url);
            NSLog(@"\n请求参数:\n%@",params);
            //NSLog(@"\n网络请求结果:\n%@",response.result);
#else
            
#endif
            if ([response.responseData isKindOfClass:[NSDictionary class]]) {
                [self.resultMessage setResult:[[response.responseData valueForKey:self.code] intValue]];
                [self.resultMessage setMessage:[response.responseData valueForKey:self.message]];
            }
            NSInteger netCode = [(NSHTTPURLResponse *)task.response statusCode];
            [self.resultMessage setNetCode:netCode];
            //设置异常信息
            [self setAbnormalInfo];
            if (netCode != 200) {
                FAILURE(HKServiceErrorServer);
            }else if(self.resultMessage.result ==  HKServiceResultSuccess){
                if (self.shouldCache) {
                    if ([response.requestParams isKindOfClass:[NSDictionary class]]) {
                        [self.cache saveCacheWithData:response.responseData serviceIdentifier:HKServiceRoot methodName:url requestParams:response.requestParams];
                    }
                }
                //NSLog(@"服务器返回数据 \n%@",response.result);
                success?success(response,self.resultMessage):nil;
            }else{
                FAILURE(HKServiceErrorNone);
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            HKNetStrongSelf
            NSInteger netCode = [(NSHTTPURLResponse *)task.response statusCode];
            [self.resultMessage setNetCode:netCode];
            //设置异常信息
            [self setAbnormalInfo];
            FAILURE(HKServiceErrorNetwork);
        }];
    }else {
         FAILURE(HKServiceErrorNetwork);
    }
}
- (void)sendPOSTWithUrl:(NSString*)url params:(NSDictionary*)params success:(HKCallBack)success failure:(HKCallBack)failure {
    [self sendPOSTWithUrl:url isFormData:NO params:params success:success failure:failure];
}
- (void)sendPOSTWithFormDataUrl:(NSString*)url params:(NSDictionary*)params success:(HKCallBack)success failure:(HKCallBack)failure {
    [self sendPOSTWithUrl:url isFormData:YES params:params success:success failure:failure];
}
- (void)sendPOSTWithUrl:(NSString*)url isFormData:(BOOL)isFormData params:(NSDictionary*)params success:(HKCallBack)success failure:(HKCallBack)failure {
    _success = [success copy];
    _failure = [failure copy];
    NSLog(@"requestUrl --------- %@ ",url);
    if (_shouldCache && [self hasCacheWithUrl:url Params:params]) {
        return;
    }
    if (self.isReachable) {
        [self addRequestHeaderWithIsFormData:isFormData];//默认非表单提交
        HKNetWeakSelf
        [_sessionManager POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            HKNetStrongSelf
            HKURLResponse *response = [[HKURLResponse alloc]initWithSessionDataTask:task
                                                                      requestParams:params
                                                                       responseData:responseObject
                                                                             status:HKResponseStatusSuccess];
            
#if HK_DEBUG
            NSLog(@"\n网络请求url:\n%@",url);
            NSLog(@"\n请求参数:\n%@",params);
//            NSLog(@"\n网络请求结果:\n%@",response.result);
#else
            
#endif
            if ([response.responseData isKindOfClass:[NSDictionary class]]) {
                [self.resultMessage setResult:[[response.responseData valueForKey:self.code] intValue]];
                [self.resultMessage setMessage:[response.responseData valueForKey:self.message]];
            }
            NSInteger netCode = [(NSHTTPURLResponse *)task.response statusCode];
            [self.resultMessage setNetCode:netCode];
            //设置异常信息
            [self setAbnormalInfo];
            if (netCode != 200) {
                FAILURE(HKServiceErrorServer);
            }else if(self.resultMessage.result ==  HKServiceResultSuccess){
                if (self.shouldCache) {
                    if ([response.requestParams isKindOfClass:[NSDictionary class]]) {
                        [self.cache saveCacheWithData:response.responseData serviceIdentifier:HKServiceRoot methodName:url requestParams:response.requestParams];
                    }
                }
                NSLog(@"服务器返回数据 \n%@",response.result);
                success?success(response,self.resultMessage):nil;
            }else{
                FAILURE(HKServiceErrorNone);
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            HKNetStrongSelf
            NSInteger netCode = [(NSHTTPURLResponse *)task.response statusCode];
            [self.resultMessage setNetCode:netCode];
            //设置异常信息
            [self setAbnormalInfo];
            FAILURE(HKServiceErrorNetwork);
        }];
        
    }else {
        FAILURE(HKServiceErrorNetwork);
    }
}

#pragma mark ---- pravited method-------
- (void)setAbnormalInfo {
    if (self.abnormalBlock) {
        self.abnormalBlock(self.resultMessage);
    }
}

-(void)addRequestHeaderWithIsFormData:(BOOL)isFormData{
    
    
    ///FIXME:公共请求头
    [_sessionManager.requestSerializer setValue:isFormData ? @"application/x-www-form-urlencoded;" : @"application/json;text/plain;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    //APP BUILD 版本号
    [_sessionManager.requestSerializer setValue: [[NSBundle mainBundle] objectForInfoDictionaryKey:NET_BundleVersion] forHTTPHeaderField:@"version"];
    //UUID
    NSString * uniqueDeviceId = [NSString stringWithFormat:@"%@",[UIDevice currentDevice].identifierForVendor];
    [_sessionManager.requestSerializer setValue:MyUUID.length?MyUUID:uniqueDeviceId forHTTPHeaderField:@"imei"];
    
    if (self.requestHeaderBlock) {
        self.requestHeaderBlock(_sessionManager);
    }
    
#if HK_SHOW_REQUESTHEAD_INFO
    NSDictionary *headers = [_sessionManager.requestSerializer HTTPRequestHeaders];
    NSEnumerator * keys = [headers keyEnumerator];
    NSString *key;
    while (key=[keys nextObject]) {
        NSLog(@"[request]%@=%@",key, [headers valueForKey:key]);
    }
#endif
}

- (BOOL)hasCacheWithUrl:(NSString *)url Params:(NSDictionary *)params
{
    if ([params isKindOfClass:[NSDictionary class]]) {
        NSString *serviceIdentifier = HKServiceRoot;
        NSString *methodName = url;
        NSData *result = [self.cache fetchCachedDataWithServiceIdentifier:serviceIdentifier methodName:methodName requestParams:params];
        
        if (result == nil) {
            return NO;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            HKURLResponse *response = [[HKURLResponse alloc] initWithData:result];
            response.requestParams = params;
            self.success(response,self.resultMessage);
        });
        return YES;
        
    }
    return NO;
}

#pragma mark - setter and getter

- (BOOL)isReachable
{
    if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusUnknown) {
        return YES;
    } else {
        return [[AFNetworkReachabilityManager sharedManager] isReachable];
    }
}

- (BOOL)isReachableViaWWAN {
    return [[AFNetworkReachabilityManager sharedManager] isReachableViaWWAN];
}

- (BOOL)isReachableViaWiFi {
    return [[AFNetworkReachabilityManager sharedManager] isReachableViaWiFi];
}

- (HKCache *)cache
{
    if (_cache == nil) {
        _cache = [HKCache sharedInstance];
    }
    return _cache;
}

@end
